home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / common.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  20KB  |  815 lines

  1. /*********************************************************************
  2.  
  3.   common.c
  4.  
  5.   Generic functions, mostly ROM and graphics related.
  6.  
  7. *********************************************************************/
  8.  
  9. #include "driver.h"
  10. #include "png.h"
  11.  
  12. /* These globals are only kept on a machine basis - LBO 042898 */
  13. unsigned int dispensed_tickets;
  14. unsigned int coins[COIN_COUNTERS];
  15. unsigned int lastcoin[COIN_COUNTERS];
  16. unsigned int coinlockedout[COIN_COUNTERS];
  17.  
  18.  
  19.  
  20. void showdisclaimer(void)   /* MAURY_BEGIN: dichiarazione */
  21. {
  22.     printf("MAME is an emulator: it reproduces, more or less faithfully, the behaviour of\n"
  23.          "several arcade machines. But hardware is useless without software, so an image\n"
  24.          "of the ROMs which run on that hardware is required. Such ROMs, like any other\n"
  25.          "commercial software, are copyrighted material and it is therefore illegal to\n"
  26.          "use them if you don't own the original arcade machine. Needless to say, ROMs\n"
  27.          "are not distributed together with MAME. Distribution of MAME together with ROM\n"
  28.          "images is a violation of copyright law and should be promptly reported to the\n"
  29.          "authors so that appropriate legal action can be taken.\n\n");
  30. }                           /* MAURY_END: dichiarazione */
  31.  
  32.  
  33. /***************************************************************************
  34.  
  35.   Read ROMs into memory.
  36.  
  37.   Arguments:
  38.   const struct RomModule *romp - pointer to an array of Rommodule structures,
  39.                                  as defined in common.h.
  40.  
  41. ***************************************************************************/
  42.  
  43. int readroms(void)
  44. {
  45.     int region;
  46.     const struct RomModule *romp;
  47.     int warning = 0;
  48.     int fatalerror = 0;
  49.     int total_roms,current_rom;
  50.     char buf[4096] = "";
  51.  
  52.  
  53.     total_roms = current_rom = 0;
  54.     romp = Machine->gamedrv->rom;
  55.  
  56.     if (!romp) return 0;
  57.  
  58.     while (romp->name || romp->offset || romp->length)
  59.     {
  60.         if (romp->name && romp->name != (char *)-1)
  61.             total_roms++;
  62.  
  63.         romp++;
  64.     }
  65.  
  66.  
  67.     romp = Machine->gamedrv->rom;
  68.  
  69.     for (region = 0;region < MAX_MEMORY_REGIONS;region++)
  70.         Machine->memory_region[region] = 0;
  71.  
  72.     region = 0;
  73.  
  74.     while (romp->name || romp->offset || romp->length)
  75.     {
  76.         unsigned int region_size;
  77.         const char *name;
  78.  
  79.         /* Mish:  An 'optional' rom region, only loaded if sound emulation is turned on */
  80.         if (Machine->sample_rate==0 && (romp->crc & REGIONFLAG_SOUNDONLY)) {
  81.             logerror("readroms():  Ignoring rom region %d\n",region);
  82.             Machine->memory_region_type[region] = romp->crc;
  83.             region++;
  84.  
  85.             romp++;
  86.             while (romp->name || romp->length)
  87.                 romp++;
  88.  
  89.             continue;
  90.         }
  91.  
  92.         if (romp->name || romp->length)
  93.         {
  94.             printf("Error in RomModule definition: expecting ROM_REGION\n");
  95.             goto getout;
  96.         }
  97.  
  98.         region_size = romp->offset;
  99.         if ((Machine->memory_region[region] = malloc(region_size)) == 0)
  100.         {
  101.             printf("readroms():  Unable to allocate %d bytes of RAM\n",region_size);
  102.             goto getout;
  103.         }
  104.         Machine->memory_region_length[region] = region_size;
  105.         Machine->memory_region_type[region] = romp->crc;
  106.  
  107.         /* some games (i.e. Pleiades) want the memory clear on startup */
  108.         if (region_size <= 0x400000)    /* don't clear large regions which will be filled anyway */
  109.             memset(Machine->memory_region[region],0,region_size);
  110.  
  111.         romp++;
  112.  
  113.         while (romp->length)
  114.         {
  115.             void *f;
  116.             int expchecksum = romp->crc;
  117.             int    explength = 0;
  118.  
  119.  
  120.             if (romp->name == 0)
  121.             {
  122.                 printf("Error in RomModule definition: ROM_CONTINUE not preceded by ROM_LOAD\n");
  123.                 goto getout;
  124.             }
  125.             else if (romp->name == (char *)-1)
  126.             {
  127.                 printf("Error in RomModule definition: ROM_RELOAD not preceded by ROM_LOAD\n");
  128.                 goto getout;
  129.             }
  130.  
  131.             name = romp->name;
  132.  
  133.             /* update status display */
  134.             if (osd_display_loading_rom_message(name,++current_rom,total_roms) != 0)
  135.                goto getout;
  136.  
  137.             {
  138.                 const struct GameDriver *drv;
  139.  
  140.                 drv = Machine->gamedrv;
  141.                 do
  142.                 {
  143.                     f = osd_fopen(drv->name,name,OSD_FILETYPE_ROM,0);
  144.                     drv = drv->clone_of;
  145.                 } while (f == 0 && drv);
  146.  
  147.                 if (f == 0)
  148.                 {
  149.                     /* NS981003: support for "load by CRC" */
  150.                     char crc[9];
  151.  
  152.                     sprintf(crc,"%08x",romp->crc);
  153.                     drv = Machine->gamedrv;
  154.                     do
  155.                     {
  156.                         f = osd_fopen(drv->name,crc,OSD_FILETYPE_ROM,0);
  157.                         drv = drv->clone_of;
  158.                     } while (f == 0 && drv);
  159.                 }
  160.             }
  161.  
  162.             if (f)
  163.             {
  164.                 do
  165.                 {
  166.                     unsigned char *c;
  167.                     unsigned int i;
  168.                     int length = romp->length & ~ROMFLAG_MASK;
  169.  
  170.  
  171.                     if (romp->name == (char *)-1)
  172.                         osd_fseek(f,0,SEEK_SET);    /* ROM_RELOAD */
  173.                     else
  174.                         explength += length;
  175.  
  176.                     if (romp->offset + length > region_size ||
  177.                         (!(romp->length & ROMFLAG_NIBBLE) && (romp->length & ROMFLAG_ALTERNATE)
  178.                                 && (romp->offset&~1) + 2*length > region_size))
  179.                     {
  180.                         printf("Error in RomModule definition: %s out of memory region space\n",name);
  181.                         osd_fclose(f);
  182.                         goto getout;
  183.                     }
  184.  
  185.                     if (romp->length & ROMFLAG_NIBBLE)
  186.                     {
  187.                         unsigned char *temp;
  188.  
  189.  
  190.                         temp = malloc(length);
  191.  
  192.                         if (!temp)
  193.                         {
  194.                             printf("Out of memory reading ROM %s\n",name);
  195.                             osd_fclose(f);
  196.                             goto getout;
  197.                         }
  198.  
  199.                         if (osd_fread(f,temp,length) != length)
  200.                         {
  201.                             printf("Unable to read ROM %s\n",name);
  202.                         }
  203.  
  204.                         /* ROM_LOAD_NIB_LOW and ROM_LOAD_NIB_HIGH */
  205.                         c = Machine->memory_region[region] + romp->offset;
  206.                         if (romp->length & ROMFLAG_ALTERNATE)
  207.                         {
  208.                             /* Load into the high nibble */
  209.                             for (i = 0;i < length;i ++)
  210.                             {
  211.                                 c[i] = (c[i] & 0x0f) | ((temp[i] & 0x0f) << 4);
  212.                             }
  213.                         }
  214.                         else
  215.                         {
  216.                             /* Load into the low nibble */
  217.                             for (i = 0;i < length;i ++)
  218.                             {
  219.                                 c[i] = (c[i] & 0xf0) | (temp[i] & 0x0f);
  220.                             }
  221.                         }
  222.  
  223.                         free (temp);
  224.                     }
  225.                     else if (romp->length & ROMFLAG_ALTERNATE)
  226.                     {
  227.                         /* ROM_LOAD_EVEN and ROM_LOAD_ODD */
  228.                         /* copy the ROM data */
  229.                     #ifdef LSB_FIRST
  230.                         c = Machine->memory_region[region] + (romp->offset ^ 1);
  231.                     #else
  232.                         c = Machine->memory_region[region] + romp->offset;
  233.                     #endif
  234.  
  235.                         if (osd_fread_scatter(f,c,length,2) != length)
  236.                         {
  237.                             printf("Unable to read ROM %s\n",name);
  238.                         }
  239.                     }
  240.                     else if (romp->length & ROMFLAG_QUAD) {
  241.                         static int which_quad=0; /* This is multi session friendly, as we only care about the modulus */
  242.                         unsigned char *temp;
  243.                         int base=0;
  244.  
  245.                         temp = malloc(length);    /* Need to load rom to temporary space */
  246.                         osd_fread(f,temp,length);
  247.  
  248.                         /* Copy quad to region */
  249.                         c = Machine->memory_region[region] + romp->offset;
  250.  
  251.                     #ifdef LSB_FIRST
  252.                         switch (which_quad%4) {
  253.                             case 0: base=1; break;
  254.                             case 1: base=0; break;
  255.                             case 2: base=3; break;
  256.                             case 3: base=2; break;
  257.                         }
  258.                     #else
  259.                         switch (which_quad%4) {
  260.                             case 0: base=0; break;
  261.                             case 1: base=1; break;
  262.                             case 2: base=2; break;
  263.                             case 3: base=3; break;
  264.                         }
  265.                     #endif
  266.  
  267.                         for (i=base; i< length*4; i += 4)
  268.                             c[i]=temp[i/4];
  269.  
  270.                         which_quad++;
  271.                         free(temp);
  272.                     }
  273.                     else
  274.                     {
  275.                         int wide = romp->length & ROMFLAG_WIDE;
  276.                     #ifdef LSB_FIRST
  277.                         int swap = (romp->length & ROMFLAG_SWAP) ^ ROMFLAG_SWAP;
  278.                     #else
  279.                         int swap = romp->length & ROMFLAG_SWAP;
  280.                     #endif
  281.  
  282.                         osd_fread(f,Machine->memory_region[region] + romp->offset,length);
  283.  
  284.                         /* apply swappage */
  285.                         c = Machine->memory_region[region] + romp->offset;
  286.                         if (wide && swap)
  287.                         {
  288.                             for (i = 0; i < length; i += 2)
  289.                             {
  290.                                 int temp = c[i];
  291.                                 c[i] = c[i+1];
  292.                                 c[i+1] = temp;
  293.                             }
  294.                         }
  295.                     }
  296.  
  297.                     romp++;
  298.                 } while (romp->length && (romp->name == 0 || romp->name == (char *)-1));
  299.  
  300.                 if (explength != osd_fsize (f))
  301.                 {
  302.                     sprintf (&buf[strlen(buf)], "%-12s WRONG LENGTH (expected: %08x found: %08x)\n",
  303.                             name,explength,osd_fsize(f));
  304.                     warning = 1;
  305.                 }
  306.  
  307.                 if (expchecksum != osd_fcrc (f))
  308.                 {
  309.                     warning = 1;
  310.                     if (expchecksum == 0)
  311.                         sprintf(&buf[strlen(buf)],"%-12s NO GOOD DUMP KNOWN\n",name);
  312.                     else if (expchecksum == BADCRC(osd_fcrc(f)))
  313.                         sprintf(&buf[strlen(buf)],"%-12s ROM NEEDS REDUMP\n",name);
  314.                     else
  315.                         sprintf(&buf[strlen(buf)], "%-12s WRONG CRC (expected: %08x found: %08x)\n",
  316.                                 name,expchecksum,osd_fcrc(f));
  317.                 }
  318.  
  319.                 osd_fclose(f);
  320.             }
  321.             else
  322.             {
  323.                 /* allow for a NO GOOD DUMP KNOWN rom to be missing */
  324.                 if (expchecksum == 0)
  325.                 {
  326.                     sprintf (&buf[strlen(buf)], "%-12s NOT FOUND (NO GOOD DUMP KNOWN)\n",name);
  327.                     warning = 1;
  328.                 }
  329.                 else
  330.                 {
  331.                     sprintf (&buf[strlen(buf)], "%-12s NOT FOUND\n",name);
  332.                     fatalerror = 1;
  333.                 }
  334.  
  335.                 do
  336.                 {
  337.                     if (fatalerror == 0)
  338.                     {
  339.                         int i;
  340.  
  341.                         /* fill space with random data */
  342.                         if (romp->length & ROMFLAG_ALTERNATE)
  343.                         {
  344.                             unsigned char *c;
  345.  
  346.                             /* ROM_LOAD_EVEN and ROM_LOAD_ODD */
  347.                         #ifdef LSB_FIRST
  348.                             c = Machine->memory_region[region] + (romp->offset ^ 1);
  349.                         #else
  350.                             c = Machine->memory_region[region] + romp->offset;
  351.                         #endif
  352.  
  353.                             for (i = 0;i < (romp->length & ~ROMFLAG_MASK);i++)
  354.                                 c[2*i] = rand();
  355.                         }
  356.                         else
  357.                         {
  358.                             for (i = 0;i < (romp->length & ~ROMFLAG_MASK);i++)
  359.                                 Machine->memory_region[region][romp->offset + i] = rand();
  360.                         }
  361.                     }
  362.                     romp++;
  363.                 } while (romp->length && (romp->name == 0 || romp->name == (char *)-1));
  364.             }
  365.         }
  366.  
  367.         region++;
  368.     }
  369.  
  370.     /* final status display */
  371.     osd_display_loading_rom_message(0,current_rom,total_roms);
  372.  
  373.     if (warning || fatalerror)
  374.     {
  375.         extern int bailing;
  376.  
  377.         if (fatalerror)
  378.         {
  379.             strcat (buf, "ERROR: required files are missing, the game cannot be run.\n");
  380.             bailing = 1;
  381.         }
  382.         else
  383.             strcat (buf, "WARNING: the game might not run correctly.\n");
  384.         printf ("%s", buf);
  385.  
  386.         if (!options.gui_host && !bailing)
  387.         {
  388.             printf ("Press any key to continue\n");
  389.             keyboard_read_sync();
  390.             if (keyboard_pressed(KEYCODE_LCONTROL) && keyboard_pressed(KEYCODE_C))
  391.                 return 1;
  392.         }
  393.     }
  394.  
  395.     if (fatalerror) return 1;
  396.     else return 0;
  397.  
  398.  
  399. getout:
  400.     /* final status display */
  401.     osd_display_loading_rom_message(0,current_rom,total_roms);
  402.  
  403.     for (region = 0;region < MAX_MEMORY_REGIONS;region++)
  404.     {
  405.         free(Machine->memory_region[region]);
  406.         Machine->memory_region[region] = 0;
  407.     }
  408.  
  409.     return 1;
  410. }
  411.  
  412.  
  413. void printromlist(const struct RomModule *romp,const char *basename)
  414. {
  415.     if (!romp) return;
  416.  
  417. #ifdef MESS
  418.     if (!strcmp(basename,"nes")) return;
  419. #endif
  420.  
  421.     printf("This is the list of the ROMs required for driver \"%s\".\n"
  422.             "Name              Size       Checksum\n",basename);
  423.  
  424.     while (romp->name || romp->offset || romp->length)
  425.     {
  426.         romp++;    /* skip memory region definition */
  427.  
  428.         while (romp->length)
  429.         {
  430.             const char *name;
  431.             int length,expchecksum;
  432.  
  433.  
  434.             name = romp->name;
  435.             expchecksum = romp->crc;
  436.  
  437.             length = 0;
  438.  
  439.             do
  440.             {
  441.                 /* ROM_RELOAD */
  442.                 if (romp->name == (char *)-1)
  443.                     length = 0;    /* restart */
  444.  
  445.                 length += romp->length & ~ROMFLAG_MASK;
  446.  
  447.                 romp++;
  448.             } while (romp->length && (romp->name == 0 || romp->name == (char *)-1));
  449.  
  450.             if (expchecksum)
  451.                 printf("%-12s  %7d bytes  %08x\n",name,length,expchecksum);
  452.             else
  453.                 printf("%-12s  %7d bytes  NO GOOD DUMP KNOWN\n",name,length);
  454.         }
  455.     }
  456. }
  457.  
  458.  
  459.  
  460. /***************************************************************************
  461.  
  462.   Read samples into memory.
  463.   This function is different from readroms() because it doesn't fail if
  464.   it doesn't find a file: it will load as many samples as it can find.
  465.  
  466. ***************************************************************************/
  467.  
  468. #ifdef LSB_FIRST
  469. #define intelLong(x) (x)
  470. #else
  471. #define intelLong(x) (((x << 24) | (((unsigned long) x) >> 24) | (( x & 0x0000ff00) << 8) | (( x & 0x00ff0000) >> 8)))
  472. #endif
  473.  
  474. static struct GameSample *read_wav_sample(void *f)
  475. {
  476.     unsigned long offset = 0;
  477.     UINT32 length, rate, filesize, temp32;
  478.     UINT16 bits, temp16;
  479.     char buf[32];
  480.     struct GameSample *result;
  481.  
  482.     /* read the core header and make sure it's a WAVE file */
  483.     offset += osd_fread(f, buf, 4);
  484.     if (offset < 4)
  485.         return NULL;
  486.     if (memcmp(&buf[0], "RIFF", 4) != 0)
  487.         return NULL;
  488.  
  489.     /* get the total size */
  490.     offset += osd_fread(f, &filesize, 4);
  491.     if (offset < 8)
  492.         return NULL;
  493.     filesize = intelLong(filesize);
  494.  
  495.     /* read the RIFF file type and make sure it's a WAVE file */
  496.     offset += osd_fread(f, buf, 4);
  497.     if (offset < 12)
  498.         return NULL;
  499.     if (memcmp(&buf[0], "WAVE", 4) != 0)
  500.         return NULL;
  501.  
  502.     /* seek until we find a format tag */
  503.     while (1)
  504.     {
  505.         offset += osd_fread(f, buf, 4);
  506.         offset += osd_fread(f, &length, 4);
  507.         length = intelLong(length);
  508.         if (memcmp(&buf[0], "fmt ", 4) == 0)
  509.             break;
  510.  
  511.         /* seek to the next block */
  512.         osd_fseek(f, length, SEEK_CUR);
  513.         offset += length;
  514.         if (offset >= filesize)
  515.             return NULL;
  516.     }
  517.  
  518.     /* read the format -- make sure it is PCM */
  519.     offset += osd_fread_lsbfirst(f, &temp16, 2);
  520.     if (temp16 != 1)
  521.         return NULL;
  522.  
  523.     /* number of channels -- only mono is supported */
  524.     offset += osd_fread_lsbfirst(f, &temp16, 2);
  525.     if (temp16 != 1)
  526.         return NULL;
  527.  
  528.     /* sample rate */
  529.     offset += osd_fread(f, &rate, 4);
  530.     rate = intelLong(rate);
  531.  
  532.     /* bytes/second and block alignment are ignored */
  533.     offset += osd_fread(f, buf, 6);
  534.  
  535.     /* bits/sample */
  536.     offset += osd_fread_lsbfirst(f, &bits, 2);
  537.     if (bits != 8 && bits != 16)
  538.         return NULL;
  539.  
  540.     /* seek past any extra data */
  541.     osd_fseek(f, length - 16, SEEK_CUR);
  542.     offset += length - 16;
  543.  
  544.     /* seek until we find a data tag */
  545.     while (1)
  546.     {
  547.         offset += osd_fread(f, buf, 4);
  548.         offset += osd_fread(f, &length, 4);
  549.         length = intelLong(length);
  550.         if (memcmp(&buf[0], "data", 4) == 0)
  551.             break;
  552.  
  553.         /* seek to the next block */
  554.         osd_fseek(f, length, SEEK_CUR);
  555.         offset += length;
  556.         if (offset >= filesize)
  557.             return NULL;
  558.     }
  559.  
  560.     /* allocate the game sample */
  561.     result = malloc(sizeof(struct GameSample) + length);
  562.     if (result == NULL)
  563.         return NULL;
  564.  
  565.     /* fill in the sample data */
  566.     result->length = length;
  567.     result->smpfreq = rate;
  568.     result->resolution = bits;
  569.  
  570.     /* read the data in */
  571.     if (bits == 8)
  572.     {
  573.         osd_fread(f, result->data, length);
  574.  
  575.         /* convert 8-bit data to signed samples */
  576.         for (temp32 = 0; temp32 < length; temp32++)
  577.             result->data[temp32] ^= 0x80;
  578.     }
  579.     else
  580.     {
  581.         /* 16-bit data is fine as-is */
  582.         osd_fread_lsbfirst(f, result->data, length);
  583.     }
  584.  
  585.     return result;
  586. }
  587.  
  588. struct GameSamples *readsamples(const char **samplenames,const char *basename)
  589. /* V.V - avoids samples duplication */
  590. /* if first samplename is *dir, looks for samples into "basename" first, then "dir" */
  591. {
  592.     int i;
  593.     struct GameSamples *samples;
  594.     int skipfirst = 0;
  595.  
  596.     /* if the user doesn't want to use samples, bail */
  597.     if (!options.use_samples) return 0;
  598.  
  599.     if (samplenames == 0 || samplenames[0] == 0) return 0;
  600.  
  601.     if (samplenames[0][0] == '*')
  602.         skipfirst = 1;
  603.  
  604.     i = 0;
  605.     while (samplenames[i+skipfirst] != 0) i++;
  606.  
  607.     if (!i) return 0;
  608.  
  609.     if ((samples = malloc(sizeof(struct GameSamples) + (i-1)*sizeof(struct GameSample))) == 0)
  610.         return 0;
  611.  
  612.     samples->total = i;
  613.     for (i = 0;i < samples->total;i++)
  614.         samples->sample[i] = 0;
  615.  
  616.     for (i = 0;i < samples->total;i++)
  617.     {
  618.         void *f;
  619.  
  620.         if (samplenames[i+skipfirst][0])
  621.         {
  622.             if ((f = osd_fopen(basename,samplenames[i+skipfirst],OSD_FILETYPE_SAMPLE,0)) == 0)
  623.                 if (skipfirst)
  624.                     f = osd_fopen(samplenames[0]+1,samplenames[i+skipfirst],OSD_FILETYPE_SAMPLE,0);
  625.             if (f != 0)
  626.             {
  627.                 samples->sample[i] = read_wav_sample(f);
  628.                 osd_fclose(f);
  629.             }
  630.         }
  631.     }
  632.  
  633.     return samples;
  634. }
  635.  
  636.  
  637. void freesamples(struct GameSamples *samples)
  638. {
  639.     int i;
  640.  
  641.  
  642.     if (samples == 0) return;
  643.  
  644.     for (i = 0;i < samples->total;i++)
  645.         free(samples->sample[i]);
  646.  
  647.     free(samples);
  648. }
  649.  
  650.  
  651.  
  652. unsigned char *memory_region(int num)
  653. {
  654.     int i;
  655.  
  656.     if (num < MAX_MEMORY_REGIONS)
  657.         return Machine->memory_region[num];
  658.     else
  659.     {
  660.         for (i = 0;i < MAX_MEMORY_REGIONS;i++)
  661.         {
  662.             if ((Machine->memory_region_type[i] & ~REGIONFLAG_MASK) == num)
  663.                 return Machine->memory_region[i];
  664.         }
  665.     }
  666.  
  667.     return 0;
  668. }
  669.  
  670. int memory_region_length(int num)
  671. {
  672.     int i;
  673.  
  674.     if (num < MAX_MEMORY_REGIONS)
  675.         return Machine->memory_region_length[num];
  676.     else
  677.     {
  678.         for (i = 0;i < MAX_MEMORY_REGIONS;i++)
  679.         {
  680.             if ((Machine->memory_region_type[i] & ~REGIONFLAG_MASK) == num)
  681.                 return Machine->memory_region_length[i];
  682.         }
  683.     }
  684.  
  685.     return 0;
  686. }
  687.  
  688. int new_memory_region(int num, int length)
  689. {
  690.     int i;
  691.  
  692.     if (num < MAX_MEMORY_REGIONS)
  693.     {
  694.         Machine->memory_region_length[num] = length;
  695.         Machine->memory_region[num] = malloc(length);
  696.         return (Machine->memory_region[num] == NULL) ? 1 : 0;
  697.     }
  698.     else
  699.     {
  700.         for (i = 0;i < MAX_MEMORY_REGIONS;i++)
  701.         {
  702.             if (Machine->memory_region[i] == NULL)
  703.             {
  704.                 Machine->memory_region_length[i] = length;
  705.                 Machine->memory_region_type[i] = num;
  706.                 Machine->memory_region[i] = malloc(length);
  707.                 return (Machine->memory_region[i] == NULL) ? 1 : 0;
  708.             }
  709.         }
  710.     }
  711.     return 1;
  712. }
  713.  
  714. void free_memory_region(int num)
  715. {
  716.     int i;
  717.  
  718.     if (num < MAX_MEMORY_REGIONS)
  719.     {
  720.         free(Machine->memory_region[num]);
  721.         Machine->memory_region[num] = 0;
  722.     }
  723.     else
  724.     {
  725.         for (i = 0;i < MAX_MEMORY_REGIONS;i++)
  726.         {
  727.             if ((Machine->memory_region_type[i] & ~REGIONFLAG_MASK) == num)
  728.             {
  729.                 free(Machine->memory_region[i]);
  730.                 Machine->memory_region[i] = 0;
  731.                 return;
  732.             }
  733.         }
  734.     }
  735. }
  736.  
  737.  
  738. /* LBO 042898 - added coin counters */
  739. WRITE_HANDLER( coin_counter_w )
  740. {
  741.     if (offset >= COIN_COUNTERS) return;
  742.     /* Count it only if the data has changed from 0 to non-zero */
  743.     if (data && (lastcoin[offset] == 0))
  744.     {
  745.         coins[offset] ++;
  746.     }
  747.     lastcoin[offset] = data;
  748. }
  749.  
  750. WRITE_HANDLER( coin_lockout_w )
  751. {
  752.     if (offset >= COIN_COUNTERS) return;
  753.  
  754.     coinlockedout[offset] = data;
  755. }
  756.  
  757. /* Locks out all the coin inputs */
  758. WRITE_HANDLER( coin_lockout_global_w )
  759. {
  760.     int i;
  761.  
  762.     for (i = 0; i < COIN_COUNTERS; i++)
  763.     {
  764.         coin_lockout_w(i, data);
  765.     }
  766. }
  767.  
  768.  
  769.  
  770. int snapno;
  771.  
  772. void save_screen_snapshot(void)
  773. {
  774.     void *fp;
  775.     char name[20];
  776.  
  777.  
  778.     /* avoid overwriting existing files */
  779.     /* first of all try with "gamename.png" */
  780.     sprintf(name,"%.8s", Machine->gamedrv->name);
  781.     if (osd_faccess(name,OSD_FILETYPE_SCREENSHOT))
  782.     {
  783.         do
  784.         {
  785.             /* otherwise use "nameNNNN.png" */
  786.             sprintf(name,"%.4s%04d",Machine->gamedrv->name,snapno++);
  787.         } while (osd_faccess(name, OSD_FILETYPE_SCREENSHOT));
  788.     }
  789.  
  790.     if ((fp = osd_fopen(Machine->gamedrv->name, name, OSD_FILETYPE_SCREENSHOT, 1)) != NULL)
  791.     {
  792.         if (Machine->drv->video_attributes & VIDEO_TYPE_VECTOR)
  793.             png_write_bitmap(fp,Machine->scrbitmap);
  794.         else
  795.         {
  796.             struct osd_bitmap *bitmap;
  797.  
  798.             bitmap = osd_new_bitmap(
  799.                     Machine->drv->visible_area.max_x - Machine->drv->visible_area.min_x + 1,
  800.                     Machine->drv->visible_area.max_y - Machine->drv->visible_area.min_y + 1,
  801.                     Machine->scrbitmap->depth);
  802.  
  803.             if (bitmap)
  804.             {
  805.                 copybitmap(bitmap,Machine->scrbitmap,0,0,
  806.                         -Machine->drv->visible_area.min_x,-Machine->drv->visible_area.min_y,0,TRANSPARENCY_NONE,0);
  807.                 png_write_bitmap(fp,bitmap);
  808.                 osd_free_bitmap(bitmap);
  809.             }
  810.         }
  811.  
  812.         osd_fclose(fp);
  813.     }
  814. }
  815.